package com.gitee.neuray.security.admin.user.biz;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.gitee.neuray.security.admin.authority.AdminMenuDto;
import com.gitee.neuray.security.admin.authority.FrontPermission;
import com.gitee.neuray.security.admin.authority.PermissionElementDto;
import com.gitee.neuray.security.admin.constant.AdminCommonConstant;
import com.gitee.neuray.security.admin.dto.AdminUser;
import com.gitee.neuray.security.admin.dto.PmUserDto;
import com.gitee.neuray.security.admin.element.entity.AdminElementEntity;
import com.gitee.neuray.security.admin.exception.AdminException;
import com.gitee.neuray.security.admin.org.biz.AdminOrgBiz;
import com.gitee.neuray.security.admin.org.entity.AdminOrgEntity;
import com.gitee.neuray.security.admin.role.biz.AdminRoleBiz;
import com.gitee.neuray.security.admin.role.entity.AdminRoleEntity;
import com.gitee.neuray.security.admin.user.dto.AdminUserDto;
import com.gitee.neuray.security.admin.user.vo.AdminStaffVo;
import com.gitee.neuray.security.admin.user.vo.AdminUserVo;
import com.gitee.neuray.security.admin.userrole.biz.AdminRoleusermapBiz;
import com.gitee.neuray.security.admin.userrole.entity.AdminRoleusermapEntity;
import com.gitee.neuray.security.admin.userrole.mapper.AdminRoleusermapMapper;
import com.gitee.neuray.security.admin.vo.FrontUser;
import com.gitee.neuray.security.admin.vo.UserRole;
import com.gitee.neuray.security.auth.client.config.SysAuthConfig;
import com.gitee.neuray.security.auth.client.jwt.UserAuthUtil;
import com.gitee.neuray.security.common.constant.UserConstant;
import com.gitee.neuray.security.common.exception.BaseException;
import com.gitee.neuray.security.common.msg.TableResultResponse;
import com.gitee.neuray.security.common.util.Query;
import com.github.pagehelper.Page;
import com.github.pagehelper.PageHelper;
import org.apache.catalina.User;
import org.apache.poi.ss.formula.functions.T;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.stereotype.Service;

import java.lang.reflect.ParameterizedType;
import java.util.*;
import java.util.stream.Collectors;

import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;
import tk.mybatis.mapper.common.Mapper;
import com.gitee.neuray.security.common.biz.BaseBiz;

import com.gitee.neuray.security.admin.user.mapper.AdminStaffMapper;
import com.gitee.neuray.security.admin.user.entity.AdminStaffEntity;
import tk.mybatis.mapper.entity.Example;


@Service
@Transactional(rollbackFor = Exception.class)
public class AdminStaffBiz extends BaseBiz<AdminStaffMapper,AdminStaffEntity> {
    private BCryptPasswordEncoder encoder = new BCryptPasswordEncoder(UserConstant.PW_ENCORDER_SALT);

    @Autowired
    private SysAuthConfig sysAuthConfig;
    @Autowired
    private AdminRoleusermapBiz adminRoleusermapBiz;
    @Autowired
    private AdminRoleBiz adminRoleBiz;
    @Autowired
    private AdminOrgBiz adminOrgBiz;
    @Autowired
    private UserAuthUtil userAuthUtil;
    @Autowired
    private AdminRoleBiz roleBiz;
    @Autowired
    private AdminRoleusermapMapper roleUserMapper;
    @Autowired
    private AdminStaffMapper adminStaffMapper;


    @Override
    protected String getPageName() {
        return "AdminStaff"+"Biz";
    }

    /**
     * 验证用户
     * @param accout
     * @param password
     * @return
     */
    public PmUserDto validate(String accout, String password)throws Exception{
        if(StringUtils.isEmpty(accout) || StringUtils.isEmpty(password)){
            throw new AdminException("用户名或密码不能为空...");
        }
        PmUserDto pmUserDto = new PmUserDto();
        //判断是否为系统超级管理员
        if(Objects.equals(accout,sysAuthConfig.getSysUsername())){
            if(!Objects.equals(password,sysAuthConfig.getSysPassword())){
                throw new AdminException("超级管理员密码错误...");
            }
            pmUserDto.setId(sysAuthConfig.getSysUsername());
            pmUserDto.setAccout(sysAuthConfig.getSysUsername());
            pmUserDto.setPassword(sysAuthConfig.getSysPassword());
            pmUserDto.setName(sysAuthConfig.getSysUsername());
            pmUserDto.setOrgCode("root");
            return pmUserDto;
        }
        AdminStaffEntity adminStaffTemp = new AdminStaffEntity();
        adminStaffTemp.setAccout(accout);
        List<AdminStaffEntity> adminUsers = mapper.select(adminStaffTemp);
        if(adminUsers==null || adminUsers.size() == 0){
            throw new AdminException("没有该用户...");
        }
        if(adminUsers.size() > 1){
            throw new AdminException("系统中存在多个该用户名...");
        }
        if (!encoder.matches(password, adminUsers.get(0).getPassword())) {
            throw new AdminException("密码错误...");
        }
        BeanUtils.copyProperties(adminUsers.get(0),pmUserDto);
        pmUserDto.setOrgCode(adminUsers.get(0).getDeptCode());
        return pmUserDto;
    }

    /**
     * 获取所有人员
     * @return
     */
    public List<AdminStaffEntity> findStaffAll(){
        return adminStaffMapper.findStaffAll();
    }

    /**
     * 查询人员，人员前面拼接部门xxx_xxx
     * @return
     */
    public List<Map<String,Object>> listStaffAndOrg(){
        return adminStaffMapper.listStaffAndOrg();
    }

    @Override
    public void insertSelective(AdminStaffEntity entity) {
        if(!StringUtils.isEmpty(entity.getPassword())){
            entity.setPassword(encoder.encode(entity.getPassword()));
        }
        super.insertSelective(entity);
    }

    public void addUser(AdminUserDto adminUserDto)throws Exception{
        //添加用户
        AdminStaffEntity staffEntity = new AdminStaffEntity();
        BeanUtils.copyProperties(adminUserDto,staffEntity);
        //设置为1，系统创建
        staffEntity.setSjly(AdminCommonConstant.USER_SYS_CREATE_FLAG);
        insertSelective(staffEntity);
        //添加角色
        if(StringUtils.isEmpty(adminUserDto.getRoleId())){
            throw new BaseException("请设置角色...");
        }
        List<String> roleIds = adminUserDto.getRoleId();
        for(String roleId : roleIds){
            AdminRoleusermapEntity userRole = new AdminRoleusermapEntity();
            userRole.setUserId(staffEntity.getId());
            userRole.setRoleId(roleId);
            /*userRole.setUserId(staffEntity.getId());
            userRole.setRoleId(adminUserDto.getRoleId());*/
            adminRoleusermapBiz.insert(userRole);
        }
    }

    @Override
    public void updateSelectiveById(AdminStaffEntity entity) {
        if(!StringUtils.isEmpty(entity.getPassword())){
            entity.setPassword(encoder.encode(entity.getPassword()));
        }
        super.updateSelectiveById(entity);
    }

    public AdminUserVo getAdminUser(String id) throws Exception{
        if(StringUtils.isEmpty(id)){
            throw new BaseException("id不能为空...");
        }

        AdminRoleusermapEntity adminRoleusermaptemp = new AdminRoleusermapEntity();
        adminRoleusermaptemp.setUserId(id);
        List<AdminRoleusermapEntity> userRoles = adminRoleusermapBiz.selectList(adminRoleusermaptemp);
        List<AdminRoleEntity> roleIds = new ArrayList<>();
        //获取用户角色
        AdminUserVo vo = new AdminUserVo();
        if(userRoles != null ){
            for(AdminRoleusermapEntity userRole:userRoles){
                if(userRole != null && !StringUtils.isEmpty(userRole.getRoleId())){
                    AdminRoleEntity adminRoleEntity = adminRoleBiz.selectById(userRole.getRoleId());
                    roleIds.add(adminRoleEntity);
                }
            }
        }
        vo.setAdminRoleEntity(roleIds);
        //获取用户基本信息
        AdminStaffEntity adminStaffEntity = super.selectById(id);
        AdminOrgEntity adminOrgEntity = adminOrgBiz.selectById(adminStaffEntity.getDeptCode());
        AdminStaffVo adminStaffVo = new AdminStaffVo();
        BeanUtils.copyProperties(adminStaffEntity,adminStaffVo);
        if(adminOrgEntity != null){
            adminStaffVo.setDeptName(adminOrgEntity.getOrgName());
        }
        vo.setAdminStaffEntity(adminStaffVo);
        return vo;
    }

    public void updateUser(AdminUserDto userDto)throws Exception{
        AdminStaffEntity adminStaffEntity = new AdminStaffEntity();
        BeanUtils.copyProperties(userDto,adminStaffEntity);
        //更新员工的基本信息
        updateSelectiveById(adminStaffEntity);
        //更新角色信息
        if(userDto.getRoleId() != null && userDto.getRoleId().size() != 0){
            AdminRoleusermapEntity temp = new AdminRoleusermapEntity();
            temp.setUserId(userDto.getId());
            List<AdminRoleusermapEntity> userRoles = adminRoleusermapBiz.selectList(temp);
            //属于修改
            if(userRoles != null){
                List<String> roles = userDto.getRoleId();
                Example params = new Example(AdminRoleusermapEntity.class);
                params.createCriteria().andEqualTo("userId",userDto.getId());
                roleUserMapper.deleteByExample(params);

                for(String str : roles){
                    AdminRoleusermapEntity userRole = new AdminRoleusermapEntity();
                    userRole.setUserId(userDto.getId());
                    userRole.setRoleId(str);
                    adminRoleusermapBiz.insertSelective(userRole);
                }
                /*for(AdminRoleusermapEntity userRole:userRoles){
                    if(userRole != null && !StringUtils.isEmpty(userRole.getRoleId())){
                        userRole.setRoleId(userDto.getRoleId());
                        adminRoleusermapBiz.updateSelectiveById(userRole);
                        return;
                    }
                    //属于新增
                    userRole = new AdminRoleusermapEntity();
                    userRole.setUserId(userDto.getId());
                    userRole.setRoleId(userDto.getRoleId());
                    adminRoleusermapBiz.insertSelective(userRole);
                }*/
            }else{
                List<String> roles = userDto.getRoleId();
                for(String str : roles){
                    AdminRoleusermapEntity userRole = new AdminRoleusermapEntity();
                    userRole.setUserId(userDto.getId());
                    userRole.setRoleId(str);
                    adminRoleusermapBiz.insertSelective(userRole);
                }
            }
        }
    }

    public TableResultResponse<AdminUserDto> page(Query query) {
        Example example = new Example(AdminStaffEntity.class);
        //如果departcode是第一级组织,不加depat约束查询所有
        if(query.containsKey("deptCode") && AdminCommonConstant.FIRST_ORG_CODE.equals(query.get("deptCode"))){
            query.remove("deptCode");
        }
        if(query.entrySet().size()>0) {
            Example.Criteria criteria = example.createCriteria();
            for (Map.Entry<String, Object> entry : query.entrySet()) {
                if(Objects.equals("deptCode",entry.getKey())){
                    Example orgEx = new Example(AdminOrgEntity.class);
                    orgEx.createCriteria().orEqualTo("parentId",entry.getValue().toString()).orEqualTo("id",entry.getValue().toString());
                    List<AdminOrgEntity> adminOrgEntities = adminOrgBiz.selectByExample(orgEx);
                    List<String> collect = adminOrgEntities.stream().map(AdminOrgEntity::getId).collect(Collectors.toList());
                    criteria.andIn("deptCode",collect);
                    continue;
                }
                criteria.andLike(entry.getKey(), "%" + entry.getValue().toString() + "%");
            }
        }
        if(isContantsCrtTime(AdminStaffEntity.class)){
            example.setOrderByClause("CRT_TIME DESC");
        }
        Page<Object> result = PageHelper.startPage(query.getPageNo(), query.getPageSize());
        List<AdminStaffEntity> list = mapper.selectByExample(example);
        List<AdminUserDto> adminUserDtos = JSONArray.parseArray(JSONObject.toJSONString(list), AdminUserDto.class);
        for (AdminUserDto dto:
        adminUserDtos) {
            AdminOrgEntity adminOrgEntity = adminOrgBiz.selectById(dto.getDeptCode());
            if(adminOrgEntity != null){
                dto.setDeptName(adminOrgEntity.getOrgName());
            }
        }
        return new TableResultResponse<AdminUserDto>(result.getPageSize(), result.getPageNum() ,result.getPages(), result.getTotal(), adminUserDtos);
    }

    @Override
    public void deleteById(String id) {
        //删除用户
        super.deleteById(id);
        //删除角色
        AdminRoleusermapEntity temp = new AdminRoleusermapEntity();
        temp.setUserId(id);
        adminRoleusermapBiz.delete(temp);
    }

    /**
     * 获取前端用户信息
     * @param token
     * @return
     * @throws Exception
     */
    public FrontUser getUserInfo(String token) throws Exception {
        String userId;
        try{
            userId = userAuthUtil.getInfoFromToken(token).getId();
        }catch (Exception e){
            throw e;
        }
        if (userId == null) {
            return null;
        }
        FrontUser frontUser = new FrontUser();
        //如果是超级管理员，则显示所有的菜单和操作
        if(Objects.equals(sysAuthConfig.getSysUsername(),userId)){
            frontUser.setId(userAuthUtil.getInfoFromToken(token).getId());
            frontUser.setName(userAuthUtil.getInfoFromToken(token).getName());
            frontUser.setPId(userAuthUtil.getInfoFromToken(token).getUniqueName());
            frontUser.setPositions(userAuthUtil.getInfoFromToken(token).getId());
        }
        if(!Objects.equals(sysAuthConfig.getSysUsername(),userId)){
            //改为从staff表获取
            AdminStaffEntity adminStaffEntity = selectById(userId);
            BeanUtils.copyProperties(adminStaffEntity, frontUser);
            frontUser.setOrgCode(adminStaffEntity.getDeptCode());
            frontUser.setId(adminStaffEntity.getId());
        }
        // todo 现在是一个用户对多个角色
        //UserRole userRole = this.getUserRoleByUserId(userId);
        List<UserRole> userRole = this.getUserRoleByUserId(userId);
        frontUser.setUserRole(userRole);
        return frontUser;
    }

    /**
     * 获取用户角色信息
     * @param userId
     * @return
     */
    public List<UserRole> getUserRoleByUserId(String userId) {
        List<UserRole> userRoles = new ArrayList<>();
        //如果是超级管理员
        if(Objects.equals(userId,sysAuthConfig.getSysUsername())){
            UserRole userRole = new UserRole();
            userRole.setMenus(getMeusByUserId(userId));
            userRole.setId("system");
            userRole.setName("超级管理员");
            userRoles.add(userRole);
            return userRoles;
        }
        List<AdminRoleEntity> roleList = roleBiz.getRoleByUserId(userId);
        //使用list可能有点不太对劲
        // BeanUtils.copyProperties(roleList.get(0), userRole);
        // todo 循环roleList设置role的muenu
        for(AdminRoleEntity roleEntity : roleList){
            UserRole userRole = new UserRole();
            BeanUtils.copyProperties(roleEntity, userRole);
            // todo 有点问题，每个role都设置了一边相同的menu
            userRoles.add(userRole);
            userRole.setMenus(getMeusByUserId(userId));
        }
        return userRoles;
    }

    /**
     * todo:网关鉴权时调用的方法
     * 根据userId获取角色所属菜单功能
     * @param userId
     * @return
     */
    public List<PermissionElementDto> getPermissionByUserId(String userId) throws Exception {
        List<String> roleId = getRoleId(userId);
        List<PermissionElementDto> permissionElementDtos = roleBiz.checkAuthorityElements(roleId);
        return permissionElementDtos;
    }

    /**
     * pm系统登录获取路由
     * @param userId
     * @return
     */
    public List<AdminMenuDto> getMeusByUserId(String userId) {
        // 超级管理员
        if(Objects.equals(userId,sysAuthConfig.getSysUsername())) {
            return roleBiz.authorityMenus(null,true);
        }
        List<String> roleId = getRoleId(userId);
        List<AdminMenuDto> adminMenuDtos = roleBiz.authorityMenus(roleId,false);
        return adminMenuDtos;
    }

    private List<String> getRoleId(String userId){
        //String roleId = null;
        List<String> roles = new ArrayList<>();
        List<AdminRoleEntity> roleByUserId = roleBiz.getRoleByUserId(userId);
        if(roleByUserId.size()==0){
            throw new BaseException("该人员没有访问权限...");
        }
        for(AdminRoleEntity roleEntity : roleByUserId){
            roles.add(roleEntity.getId());
        }
        // roleId = roleByUserId.get(0).getId();
        return roles;
    }
}
